package com.lvmama.pangolin.util;

import com.lvmama.pangolin.busi.config.ConfigManager;
import com.lvmama.pangolin.common.StringTools;
import com.lvmama.pangolin.entity.SegVo;
import com.lvmama.pangolin.entity.match.MatchSynonymWords;
import com.lvmama.pangolin.match.service.MatchSynonymWordsService;
import org.ansj.domain.Result;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class CommonCommodityUtils {
    private static Logger logger = Logger.getLogger(CommonCommodityUtils.class);

    @Autowired
    public MatchSynonymWordsService matchSynonymWordsService;

    private List<MatchSynonymWords> synonyList = null;
    /**
     * 空字符串
     */
    private static final String NONE="";
    /**
     * 分隔符
     */
    private static final String SEPARATOR =",";
    /**
     * 该字段存在于表中，其值为：商品名称中需要被删除的字符
     */
    private static final String COMMODITY_NEED_REMOVE="COMMODITY_NEED_REMOVE";

    private static final float FLOAT_ZERO=0F;
    private static final float FLOAT_ONE=1F;
    private static final int TEN=10;
    private static final int ONE=1;
    private static final String PRENAME = "preName";
    private static final String SEGNAME = "segName";

    /**
     * 城市打分，除去城市中的特殊字符
     * @param baseCity
     * @param compareToCity
     * @return
     */
    public float cityScore(String baseCity,String compareToCity)
    {
        if((baseCity==null||NONE.equals(baseCity))||
                (compareToCity==null||NONE.equals(compareToCity)))
        {
            return FLOAT_ZERO;
        }
        if(baseCity.trim().equals(compareToCity.trim()))
        {
            return FLOAT_ONE;
        }
        return FLOAT_ZERO;
    }


    /**
     * 类型打分，除去类型中的特殊字符后完全匹配得1分，否则得0分
     * @param baseType
     * @param compareToType
     * @return
     */
    public float typeScore(String baseType,String compareToType)
    {
        switchSynonym(baseType);
        switchSynonym(compareToType);
        if(!NONE.equals(removeSpecialChar(baseType.trim())) && removeSpecialChar(baseType.trim())
                .equals(removeSpecialChar(compareToType)))
        {
            return FLOAT_ONE;
        }
        return FLOAT_ZERO;
    }


    /**
     * 价格打分
     * @param basePrice
     * @param price
     * @return
     */
    public float priceScore(String basePrice,String price)
    {
        float score = FLOAT_ZERO;
        if(StringTools.isValid(basePrice) && StringTools.isValid(price))
        {
            if(Float.valueOf(basePrice) > FLOAT_ZERO)
            {
//                float _basePrice = Float.valueOf(basePrice);
//                float _Price = Float.valueOf(price);
                Float temp = Math.abs((Float.valueOf(basePrice)-Float.valueOf(price)));
//                Float average = (Float.valueOf(basePrice)-Float.valueOf(price))/2;
//                Float variance = (_basePrice - average)*(_basePrice - average)+
//                        (_Price - average)*(_Price - average);

                score = FLOAT_ONE - temp/Float.valueOf(basePrice)*TEN;
                if(score > FLOAT_ONE || score< FLOAT_ZERO)
                {
                    score = FLOAT_ZERO;
                }
            }

        }
        return score;
    }

    /**
     * 商品名称匹配并打分
     * @param baseName
     * @param compareToName
     * @return
     */
    public double nameScore(String baseName,String compareToName)
    {
        Map<String,String> base = preCommodityName(baseName.trim());
        String base_preName = base.get(PRENAME);
        String base_segName = base.get(SEGNAME);

        Map<String,String> compare = preCommodityName(compareToName.trim());
        String compare_preName = compare.get(PRENAME);
        String compare_segName = compare.get(SEGNAME);

        if(base_preName.equals(compare_preName)||base_segName.equals(compare_segName))
        {
            return ONE;
        }else
        {
            return score(base_segName,compare_segName);
        }
    }


    public void switchSynonym(String string)
    {
        if(synonyList == null)
        {
            if(matchSynonymWordsService == null)
            {
                matchSynonymWordsService = (MatchSynonymWordsService) SpringContextUtil
                        .getBean(MatchSynonymWordsService.class);
            }
            synonyList = matchSynonymWordsService.findAll();
        }
        if(synonyList != null && !synonyList.isEmpty())
        {
            for (MatchSynonymWords matchSynonymWords : synonyList)
            {
                if(string.contains(matchSynonymWords.getSourceWord()))
                {
                    string = string.replaceAll(matchSynonymWords.getSourceWord(), matchSynonymWords.getSynonymWord());
                }
            }
        }
    }

    /**
     * 对产品的名称进行预处理
     * @param commodityName
     * @return
     */
    public Map<String,String> preCommodityName(String commodityName){
        Map<String,String> retMap = new HashMap<>();
        retMap.put(PRENAME,NONE);
        retMap.put(SEGNAME,NONE);
        if(commodityName==null||StringUtils.isEmpty(commodityName))
        {
            return retMap;
        }
        try {
            if(synonyList == null)
            {
                if(matchSynonymWordsService == null)
                {
                    matchSynonymWordsService = (MatchSynonymWordsService) SpringContextUtil
                            .getBean(MatchSynonymWordsService.class);
                }
                synonyList = matchSynonymWordsService.findAll();
            }
            if(synonyList != null && !synonyList.isEmpty())
            {
                for (MatchSynonymWords matchSynonymWords : synonyList)
                {
                    if(commodityName.contains(matchSynonymWords.getSourceWord()))
                    {
                        commodityName = commodityName.replaceAll(matchSynonymWords.getSourceWord(), matchSynonymWords.getSynonymWord());
                    }
                }
            }
            //去除商品名称中的影响匹配的字符
            commodityName = removeSpecialChar(commodityName.trim());
            Result result = ToAnalysis.parse(commodityName);
            retMap.put(PRENAME,commodityName);
            retMap.put(SEGNAME,result.toStringWithOutNature());
        }catch (Exception e){
            logger.error("数据预处理失败！" +  e.getMessage() +" : " ,e);
        }
        return retMap;
    }

    /**
     * 去除商品名称中的影响匹配的字符
     * @param str
     */
    public String removeSpecialChar(String str)
    {
        if(str==null || NONE.equals(str))
        {
            return NONE;
        }
        String[] needRemoveCharList = needRemoveCharList();
        if(needRemoveCharList==null || needRemoveCharList.length==0)
        {
            return str;
        }
        for(String _str:needRemoveCharList)
        {
            if(NONE.equals(_str))
            {
                continue;
            }
            str = str.replaceAll(_str,NONE);
        }
        return str;
    }

    /**
     * 获取需要被删除的特殊字符串列表
     * @return
     */
    public String[] needRemoveCharList()
    {
        String needRemoveStr = ConfigManager.getInstance().getParamValue(COMMODITY_NEED_REMOVE,COMMODITY_NEED_REMOVE);
        if(needRemoveStr!=null&&!"".equals(needRemoveStr))
        {
            return needRemoveStr.split(SEPARATOR);
        }else
        {
            return null;
        }

    }

    public List<SegVo> getNameList(String str)
    {
        if(!StringTools.isValid(str))
        {
            return null;
        }
        List<SegVo> ret = new ArrayList<>();
        String[] name = str.split(SEPARATOR);
        for (int i = 0; i < name.length; i++)
        {
            SegVo segVo = new SegVo();
            segVo.setName(name[i]);
            segVo.setSeq(i);
            segVo.setMatch(false);
            ret.add(segVo);
        }
        return ret;
    }

    /**
     * 预处理后的两个名称的打分
     * @param segName
     * @param msegName
     * @return
     */
    public float score(String segName,String msegName)
    {
        List<SegVo> nameList = null;
        List<SegVo> mnameList = null;
        float scroe = 0f;
        int segLen = 0;
        int msegLen = 0;
        int strLen = 0;
        int mstrLen = 0;

        int segLen_match = 0;
        int msegLen_match = 0;
        int strLen_match = 0;
        int mstrLen_match = 0;

        if(StringTools.isValid(segName))
        {
            nameList = new ArrayList<SegVo>();
            String[]  name = segName.split(",");
            for (int i = 0; i < name.length; i++)
            {
                SegVo vo = new SegVo();
                vo.setSeq(i);
                vo.setName(name[i]);
                vo.setMatch(false);
                nameList.add(vo);
                strLen += name[i].length();
                segLen ++;
            }
        }
        if(StringTools.isValid(msegName))
        {
            mnameList = new ArrayList<SegVo>();
            String[]  name = msegName.split(",");
            for (int i = 0; i < name.length; i++)
            {
                SegVo vo = new SegVo();
                vo.setSeq(i);
                vo.setName(name[i]);
                vo.setMatch(false);
                mnameList.add(vo);
                mstrLen += name[i].length();
                msegLen ++;
            }
        }
        if((nameList == null || nameList.isEmpty())
                ||(mnameList == null || mnameList.isEmpty()))
        {
            scroe = 0f;
        }else
        {
            for (SegVo seg : nameList)
            {
                String name = seg.getName();
                for (SegVo vo : mnameList)
                {
                    if(name.equals(vo.getName()))
                    {
                        if(!vo.isMatch())
                        {
                            seg.setMatch(true);
                            vo.setMatch(true);
                            segLen_match ++;
                            msegLen_match ++;
                            strLen_match += name.length();
                            mstrLen_match += name.length();
                            break;
                        }

                    }
                }
            }
            scroe = ((0.5f*segLen_match)/(segLen) + (0.5f*strLen_match)/strLen)*0.6f
                    + ((0.5f*msegLen_match)/(msegLen) + (0.5f*mstrLen_match)/mstrLen)*0.4f;
        }
        return scroe;
    }
}
